package com.tanhua.app.Service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.PageUtil;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.app.exception.BusinessException;
import com.tanhua.app.interceptor.UserHolder;
import com.tanhua.commons.utils.Constants;
import com.tanhua.config.template.OssTemplate;
import com.tanhua.dubbo.api.CommentApi;
import com.tanhua.dubbo.api.FriendApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VideoApi;
import com.tanhua.model.enums.CommentType;
import com.tanhua.model.mongo.Comment;
import com.tanhua.model.mongo.Video;
import com.tanhua.model.pojo.UserInfo;
import com.tanhua.model.vo.CommentVo;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VideoVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class SmallVideosService {
    @Autowired
    private FastFileStorageClient client;
    @Autowired
    private FdfsWebServer webServer;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private OssTemplate ossTemplate;
    @Autowired
    private MqMessageService mqMessageService;
    @DubboReference
    private VideoApi videoApi;
    @DubboReference
    private UserInfoApi userInfoApi;
    @DubboReference
    private CommentApi commentApi;
    @DubboReference
    private FriendApi friendApi;

    //    视频上传
    public void saveVideos(MultipartFile videoThumbnail, MultipartFile videoFile) throws Exception {
        if(videoThumbnail.isEmpty()||videoFile.isEmpty()){
            throw new BusinessException(ErrorResult.error());
        }
        String filename = videoThumbnail.getOriginalFilename();
        String extName = filename.substring(filename.lastIndexOf(".") + 1);
        StorePath storePath = client.uploadFile(videoFile.getInputStream(), videoFile.getSize(), extName, null);
        String videoUrl = webServer.getWebServerUrl() + storePath.getPath();
        String imageurl = ossTemplate.upload(videoThumbnail.getOriginalFilename(), videoThumbnail.getInputStream());
        Video video = new Video();
        video.setVideoUrl(videoUrl);
        video.setPicUrl(imageurl);
        video.setUserId(UserHolder.getUserId());
        video.setText("我就是我，不一样的烟火");

        String videoId = videoApi.save(video);
        if (StringUtils.isEmpty(videoId)) {
            throw new BusinessException(ErrorResult.error());
        }
        mqMessageService.sendLogMessage(UserHolder.getUserId(),"0301","video",videoId);

    }

    //    小视频列表
    @Cacheable(
            value = "videos",
            key = "T(com.tanhua.app.interceptor.UserHolder).getUserId()+'_'+#page+'_'+#pagesize"
    )
    public PageResult queryVideoList(Integer page, Integer pagesize) {
        Long userId = UserHolder.getUserId();
        String redisKey = Constants.VIDEOS_RECOMMEND + userId;
        String redisValue = redisTemplate.opsForValue().get(redisKey);
        List<Video> list = new ArrayList<>();
        int redisPages = 0;
        if(StringUtils.isNotEmpty(redisValue)){
            String[] value = redisValue.split(",");
            if((page-1)*pagesize<value.length){
                List<Long> vids = Arrays.stream(value).limit(pagesize).skip((page - 1) * pagesize)
                        .map(item -> Long.valueOf(item)).collect(Collectors.toList());
                list = videoApi.findVideoByVids(vids);
            }
            redisPages = PageUtil.totalPage(value.length, pagesize);
        }

        if(page>redisPages){
            list = videoApi.queryVideoList(page-redisPages,pagesize);
        }

        List<Long> userIds = list.stream().map(Video::getUserId).collect(Collectors.toList());
        List<UserInfo> userInfos = userInfoApi.findByUserIds(userIds);
        List<Long> friendIds = friendApi.findById(userId);
        Map<Long, UserInfo> map = userInfos.stream().collect(Collectors.toMap(UserInfo::getId, Function.identity()));
        List<VideoVo> vos = new ArrayList<>();
        for (Video video : list) {
            UserInfo userInfo = map.get(video.getUserId());
            if (userInfo != null) {
                VideoVo vo = VideoVo.init(userInfo, video);
                String key = Constants.VIDEOS_RECOMMEND+video.getId().toHexString();
                String hashKey = Constants.VIDEO_LIKE_HASHKEY+userId;
                if(redisTemplate.opsForHash().hasKey(key,hashKey)){
                    vo.setHasLiked(1);
                }
                if(friendIds.contains(userInfo.getId())){
                    vo.setHasFocus(1);
                }
                vos.add(vo);
            }
        }
        return new PageResult(page,pagesize,0,vos);
    }

    //    视频点赞
    public Integer videoLike(String videoId) {
        Long userId = UserHolder.getUserId();
        boolean flag = commentApi.hasMovement(videoId,userId, CommentType.LIKE);
        if (flag) {
            throw new BusinessException(ErrorResult.likeError());
        }
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(videoId));
        comment.setCommentType(CommentType.LIKE.getType());
        comment.setUserId(userId);
        comment.setCreated(System.currentTimeMillis());
        Integer count = commentApi.updateVideo(comment);

        String key = Constants.VIDEOS_RECOMMEND+videoId;
        String hashKey = Constants.VIDEO_LIKE_HASHKEY + userId;
        redisTemplate.opsForHash().put(key, hashKey,"1");
        mqMessageService.sendLogMessage(UserHolder.getUserId(),"0302","video",videoId);
        return count;
    }

    //    视频点赞 - 取消
    public Integer videoDislike(String videoId) {
        Long userId = UserHolder.getUserId();
        boolean flag = commentApi.hasMovement(videoId,userId, CommentType.LIKE);
        if (!flag) {
            throw new BusinessException(ErrorResult.disLikeError());
        }
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(videoId));
        comment.setCommentType(CommentType.LIKE.getType());
        comment.setUserId(userId);
        comment.setCreated(System.currentTimeMillis());
        Integer count = commentApi.removeVideo(comment);

        String key = Constants.VIDEOS_RECOMMEND+videoId;
        String hashKey = Constants.VIDEO_LIKE_HASHKEY + userId;
        redisTemplate.opsForHash().delete(key, hashKey);
        mqMessageService.sendLogMessage(UserHolder.getUserId(),"0303","video",videoId);
        return count;
    }

    //    评论列表
    public PageResult findComments(Integer page, Integer pagesize, String videoId) {
        List<Comment> comments = commentApi.findComments(videoId, CommentType.COMMENT, page, pagesize);
        if(CollUtil.isEmpty(comments)){
            return new PageResult(page,pagesize,0,new ArrayList<>());
        }
        List<Long> userIds = CollUtil.getFieldValues(comments, "userId", Long.class);
        List<UserInfo> userInfos = userInfoApi.findByUserIds(userIds);
        Map<Long, UserInfo> map = userInfos.stream()
                .collect(Collectors.toMap(UserInfo::getId, Function.identity()));
        List<CommentVo> vos = new ArrayList<>();
        for (Comment comment : comments) {
            UserInfo userInfo = map.get(comment.getUserId());
            CommentVo vo = CommentVo.init(userInfo, comment);
            vos.add(vo);
        }
        return new PageResult(page,pagesize,0,vos);
    }

    //    评论发布
    public void saveComments(String videoId, String comment) {
        Long userId = UserHolder.getUserId();
        Comment newComment = new Comment();
        newComment.setCommentType(CommentType.COMMENT.getType());
        newComment.setContent(comment);
        newComment.setPublishId(new ObjectId(videoId));
        newComment.setUserId(userId);
        newComment.setCreated(System.currentTimeMillis());
        Integer count = commentApi.updateVideo(newComment);
        mqMessageService.sendLogMessage(UserHolder.getUserId(),"0304","video",videoId);
    }

}




